# 在Jupyter中使用matplotlib显示图像需要设置为inline模式, 否则不会实现图像
# %matplotlib inline

import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf

"""
线性回归实例
"""

# 设置随机种子
np.random.seed(5)

# 直接采用np生成等差数列的方法, 生成100个点, 每个点的取值在 -1~1 之间
x_data = np.linspace(-1, 1, 100)

# y=2X+1+噪声, 其中噪声的维度与x_data一致
# np.random.randn(d0, d1, d2...)是从标准正态分布中返回一个或多个样本值,
# x_data.shape为元组, 显示张量的值
y_data = 2 * x_data + 1.0 + np.random.randn(*x_data.shape) * 0.4
# print(y_data)

'''可视化'''
# 画出随机生成的数据的散点图
plt.scatter(x_data, y_data)
# 画出y=2x+1
plt.plot(x_data, 2 * x_data + 1.0, color="red", linewidth=3)
plt.show()

'''构建模型'''
# 构建占位符
x = tf.compat.v1.placeholder("float", name="x")
y = tf.compat.v1.placeholder("float", name="y")


def model(x, w, b):
    """定义模型函数

    w为斜率, b为截距
    """
    return tf.multiply(x, w) + b


w = tf.Variable(1.0, name="w0")
b = tf.Variable(0.0, name="b0")
# pred为预测值'
pred = model(x, w, b)

'''训练模型'''
# 迭代次数(训练轮数)
train_epochs = 10
# 学习率
learning_rate = 0.05
# 采用均方差作为损失函数
# 均方差 Mean Square Error
# 交叉熵 cross-entropy
loss_function = tf.reduce_mean(tf.square(y - pred))

# 定义优化器Optimizer, 初始化一个GradientDescentOptimizer
# 设置学习率和优化目标, 最小损失
# 梯度下降优化器
optimizer = tf.compat.v1.train.GradientDescentOptimizer(learning_rate).minimize(loss_function)

# 声明会话
sess = tf.compat.v1.Session()
# 初始化变量
init = tf.compat.v1.global_variables_initializer()
sess.run(init)

'''模型训练'''
# 模型训练阶段, 设置迭代轮次,
# 每次通过将样本之歌输入模型, 进行梯度下降优化操作,
# 每轮迭代后, 绘制模型曲线
# 开始训练, 轮数为epochs, 采用SGD随机梯度下降优化方法
for epoch in range(train_epochs):
    for xs, ys in zip(x_data, y_data):
        _, loss = sess.run([optimizer, loss_function], feed_dict={x: xs, y: ys})
    b0temp = b.eval(session=sess)
    w0temp = w.eval(session=sess)
    plt.plot(x_data, w0temp * x_data + b0temp)

plt.scatter(x_data, y_data)
plt.show()

'''利用训练出来的模型进行预测'''
x_text = 3.21
predict = sess.run(pred, feed_dict={x: x_text})
print("预测值为:{}".format(predict))
